#include <string.h>

#include <ijpege_common.h>
#ifdef DMALLOC
#include <imp/dmalloc.h>
#endif

static void ijpege_icodec_param_init(ijpege_t *h, ijpege_icodec_param_t *param)
{
	memset(param, 0, sizeof(ijpege_icodec_param_t));
	param->index = h->param.index;
	param->protocol = C_JPEGE;
	param->soc = h->param.soc;
	param->i_log_level = C_LOG_INFO;
	param->ckmalloc = h->param.ckmalloc;
	param->ckfree = h->param.ckfree;
	param->ckvirt_to_phys = h->param.ckvirt_to_phys;
	param->ckphys_to_virt = h->param.ckphys_to_virt;
	param->param.jpege_param.b_tlb = h->param.b_tlb;
	param->param.jpege_param.b_use_phy = h->param.b_use_phy;
	param->param.jpege_param.b_user_fenc = h->param.b_user_fenc;
	param->param.jpege_param.i_devid = h->param.i_devid;

	param->param.jpege_param.i_csp = h->param.i_csp;
	param->param.jpege_param.i_mb_width = C_ALIGN(h->param.i_width, 16) / 16;
	param->param.jpege_param.i_mb_height = C_ALIGN(h->param.i_height, 16) / 16;
}

int ijpege_icodec_init(ijpege_t *h)
{
	ijpege_icodec_param_t param;

	ijpege_icodec_param_init(h, &param);

	if ((h->icodec = hwicodec_init(&param)) == NULL) {
		ijpege_log(h, C_LOG_ERROR, "hwicodec_init failed\n");
		goto err_hwicodec_init;
	}

	return 0;

err_hwicodec_init:
	return -1;
}

/* return bit stream size */
int ijpege_icodec_enc(ijpege_t *h)
{
	h->icodec_io.protocol.jpege.fenc.yaddr = (intptr_t)h->fenc->plane[0];
	h->icodec_io.protocol.jpege.fenc.caddr = (intptr_t)h->fenc->plane[1];
	if (h->param.b_tlb && h->param.b_user_fenc) {
		h->icodec_io.protocol.jpege.fenc_size.ysize = h->fenc->i_stride[0] * h->fenc->i_lines[0];
		h->icodec_io.protocol.jpege.fenc_size.csize = h->fenc->i_stride[1] * h->fenc->i_lines[1];
	}
	h->icodec_io.protocol.jpege.fbs = h->fbs;
	h->icodec_io.protocol.jpege.i_ql = h->fenc->i_ql;
	h->icodec_io.bslen = 0;
    ijpege_reconfig(h);

	/*直通下JPEG需要判断height几位对齐，从而配置JPEG寄存器*/
	/*i_fenc_stride参数jpeg没有使用，此处用来传递实时高度*/
	h->icodec_io.protocol.jpege.frame_width = h->param.i_width;
	h->icodec_io.protocol.jpege.frame_height = h->param.i_height;
	return hwicodec_process(h->icodec, &h->icodec_io);
}

void ijpege_icodec_deinit(ijpege_t *h)
{
	if (h->icodec != NULL) {
		hwicodec_deinit(h->icodec);
	}
}

static int ijpege_vbinfo_check(ijpege_t *h, const ijpege_vbinfo_t const *vbinfo, const int num)
{
	int fencnum = h->param.b_user_fenc ? 0 : 1;
	if (((num != C_SOC_VB_MAX) || (vbinfo == NULL))
		|| ((vbinfo[C_SOC_VB_ENC].type != C_SOC_VB_ENC) || (vbinfo[C_SOC_VB_ENC].num != fencnum))
		|| ((vbinfo[C_SOC_VB_BS].type != C_SOC_VB_BS) || (vbinfo[C_SOC_VB_BS].num != 1))) {
		ijpege_log(h, C_LOG_ERROR, "vbinfo checkout failed\n");
		goto err_vbinfo;
	}
	if (!h->param.b_user_fenc
		&& ((vbinfo[C_SOC_VB_ENC].vb[0].yptr == 0) || (vbinfo[C_SOC_VB_ENC].vb[0].cptr == 0)
		|| (vbinfo[C_SOC_VB_ENC].vb[0].i_stride < C_ALIGN(h->param.i_width, 16))
		|| (vbinfo[C_SOC_VB_ENC].vb[0].i_lines < C_ALIGN(h->param.i_height, 16)))) {
		ijpege_log(h, C_LOG_ERROR, "vbinfo.vb.encode checkout failed\n");
		goto err_vbinfo_vb_enc;
	}

	if (vbinfo[C_SOC_VB_BS].vb[0].yptr == 0) {
		ijpege_log(h, C_LOG_ERROR, "vbinfo.vb.bs checkout failed\n");
		goto err_vbinfo_vb_bs;
	}

	return 0;

err_vbinfo_vb_bs:
err_vbinfo_vb_enc:
err_vbinfo:
	return -1;
}

static inline void ijpege_icodec_init_frame(ijpege_vb_t *vb, ijpege_frame_t *frame)
{
	int i = 0;
	for (i = 0; i < 2; i++) {
		frame->i_stride[i] = vb->i_stride;
		frame->i_lines[i] = vb->i_lines / ((i == 0) ? 1 : 2);
		frame->plane[i] = (pixel *)((i == 0) ? vb->yptr : vb->cptr);
	}
}

int ijpege_icodec_request_vbinfo(ijpege_t *h)
{
	int	vbnum = 0;

	if (hwicodec_request_vbinfo(h->icodec, &h->vbinfo, &vbnum) < 0) {
		ijpege_log(h, C_LOG_ERROR, "icodec_request_vbinfo failed\n");
		goto err_icodec_request_vbinfo;
	}

	if (ijpege_vbinfo_check(h, h->vbinfo, vbnum) < 0) {
		ijpege_log(h, C_LOG_ERROR, "vbinfo_check failed\n");
		goto err_vbinfo_check;
	}

	if (h->vbinfo[C_SOC_VB_ENC].num > 0) {
		ijpege_icodec_init_frame(&h->vbinfo[C_SOC_VB_ENC].vb[0], h->fenc);
	}
	h->fbs = (uint8_t *)h->vbinfo[C_SOC_VB_BS].vb[0].yptr;

	return 0;

err_vbinfo_check:
err_icodec_request_vbinfo:
	return -1;
}

void ijpege_icodec_release_vbinfo(ijpege_t *h)
{
	hwicodec_release_vbinfo(h->icodec, h->vbinfo);
}
